package com.zxy.day0624_util.utils;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.util.List;
import java.util.Objects;

import javax.imageio.ImageIO;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.springframework.util.StringUtils;

import com.itextpdf.text.BadElementException;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfGState;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PdfWriter;

/**
 * @Auther: lenovo
 * @Date: 2021/11/2 20:04
 * @Description:
 */
public class PDFUtil {

    private static Font DEFAULT_FONT;

    static {
        try {
            BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            DEFAULT_FONT = new Font(baseFont);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 添加水印
     *
     * @param is
     *            输入流
     * @param os
     *            输出流
     * @param mainMark
     * @param rootMark
     * @throws DocumentException
     * @throws IOException
     */
    public static void markTxt(InputStream is, OutputStream os, String mainMark, String rootMark)
            throws DocumentException, IOException {
        markTxt(0.5f, 60, true, is, os, mainMark, rootMark);
    }

    /**
     * 加图片水印
     *
     * @param iconPath
     * @param is
     * @param os
     * @param rootMark
     * @throws DocumentException
     * @throws IOException
     */
    public static void markImage(String iconPath, InputStream is, OutputStream os, String rootMark)
            throws DocumentException, IOException {
        markImage(iconPath, 0.5f, 60, false, is, os, rootMark);
    }

    /**
     * 获取字体
     * @param winPath
     * @param linuxPath
     * @return
     */
    public static Font getFont(String winPath,String linuxPath){
        String fontPath = null;
        if(System.getProperty("os.name").toLowerCase().startsWith("win")){
            fontPath = winPath;
        }else{
            fontPath = linuxPath;
        }

        try {
            BaseFont baseFont = BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            return new Font(baseFont);
        }  catch (Exception e) {
            System.out.println("获取字体失败");
            e.printStackTrace();
        }

        return DEFAULT_FONT;
    }

    /**
     * 将table转化成pdf
     * @param file
     * @param title
     * @param font
     * @param imgPath
     * @param headers
     * @param props
     * @param data
     */
    public static <T> void table2PDF(String file, String title, Font font, String imgPath, List<String> headers,
                                     List<String> props, List<T> data) {
        try {

            Document document = new Document(PageSize.A4);
            PdfWriter.getInstance(document, new FileOutputStream(file));

            document.open();

            // 设置字体
            if (font == null) {
                font = DEFAULT_FONT;
            }

            // 添加title
            if (!StringUtils.isEmpty(title)) {
                writeTitle(title, document, font);
            }

            // 写数据
            PdfPTable table = new PdfPTable(headers.size());
            // 写头
            writeHeaders(font, headers, table);
            // 写数据
            writeData(font, props, data, table);

            document.add(table);

            // 图片
            if (!StringUtils.isEmpty(imgPath)) {
                writeImage(imgPath, document);
            }

            document.close();
        } catch (Exception e) {

            System.out.println("pdf生成失败");
            e.printStackTrace();
        }

        System.out.println("PDF生成成功");
    }

    /**
     * pdf转图片
     * @param pdfFile
     * @param pngFile D://test//stu.png stu1.png stu2.png
     * @return
     */
    public static boolean pdf2png(String pdfFile, String pngFile) {
        System.out.println("开始pdf生成png图片");
        try {
            // 加载pdf信息
            PDDocument pdfDocment = PDDocument.load(new File(pdfFile));
            // 获取页数
            int pages = pdfDocment.getNumberOfPages();
            // 获取pdf渲染
            PDFRenderer pdfRenderer = new PDFRenderer(pdfDocment);
            // 循环转化
            for (int i = 0; i < pages; i++) {
                BufferedImage image = pdfRenderer.renderImageWithDPI(i, 144);// page , dpi分辨率单位
                // BufferedImage image = renderer.renderImage(i, 2.5f); // 也可以 page,缩放比
                ImageIO.write(image, "PNG", new File(pngFile));
//	            ImageIO.write(image, "PNG",
//	            		new File(new StringBuffer(pngFile).insert(pdfFile.lastIndexOf("."),"_"+i ).toString()));
                System.out.println("生成成功");
            }

        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("转化失败");
            return false;
        }
        return true;
    }

    /**
     * 写入数据
     * @param font
     * @param props
     * @param data
     * @param table
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    private static <T> void writeData(Font font, List<String> props, List<T> data, PdfPTable table)
            throws NoSuchFieldException, IllegalAccessException {
        for (T t : data) {
            for (String prop : props) {
                // 根据具体字段获取实体类中当前字段对应的值
                Field field = t.getClass().getDeclaredField(prop);
                if (Objects.nonNull(field)) {
                    // 设置访问权限 private-》public
                    field.setAccessible(true);
                    // 获取字段对应的值
                    Object value = field.get(t);
                    if (Objects.nonNull(value)) {
                        // 写入
                        table.addCell(new PdfPCell(new Phrase(value.toString(), font)));
                    } else {
                        table.addCell(new PdfPCell(new Phrase("", font)));
                    }
                }else {
                    table.addCell(new PdfPCell(new Phrase("", font)));
                }
            }
        }
    }

    /**
     * 写表格头
     * @param font
     * @param headers
     * @param table
     */
    private static void writeHeaders(Font font, List<String> headers, PdfPTable table) {
        headers.forEach(item -> {
            table.addCell(new PdfPCell(new Phrase(item, font)));

        });
    }

    /**
     * 嵌入图片
     * @param imgPath
     * @param document
     * @throws BadElementException
     * @throws MalformedURLException
     * @throws IOException
     * @throws DocumentException
     */
    private static void writeImage(String imgPath, Document document)
            throws BadElementException, MalformedURLException, IOException, DocumentException {
        // 添加图片
        Image image = Image.getInstance(imgPath);
        image.setAlignment(Image.ALIGN_CENTER);
        image.scalePercent(40);// 依照比例缩放
        document.add(image);
    }

    /**
     * 写标题
     * @param title
     * @param document
     * @param font
     * @throws Exception
     */
    private static void writeTitle(String title, Document document, Font font) throws Exception {
        // 添加段落
        Paragraph paragraph = new Paragraph(title, font);
        paragraph.setAlignment(1); // 设置文字居中 0靠左 1，居中 2，靠右
        paragraph.setIndentationLeft(12); // 设置左缩进
        paragraph.setIndentationRight(12); // 设置右缩进
        paragraph.setFirstLineIndent(24); // 设置首行缩进
        paragraph.setLeading(20f); // 行间距
        paragraph.setSpacingBefore(5f); // 设置段落上空白
        paragraph.setSpacingAfter(10f); // 设置段落下空白
        document.add(paragraph);
    }

    /**
     *
     * @param alpha
     *            透明度 0-1
     * @param degree
     *            角度 0-360
     * @param isUnder
     *            水印置于文本上/下
     * @param is
     *            输入IO
     * @param os
     *            输出IO
     * @param mainMark
     *            主文本
     * @param rootMark
     *            页脚文本
     */
    private static void markTxt(float alpha, int degree, boolean isUnder, InputStream is, OutputStream os,
                                String mainMark, String rootMark) throws DocumentException, IOException {
        PdfReader reader = new PdfReader(is);
        PdfStamper stamper = new PdfStamper(reader, os);

        try {
            PdfGState gs = new PdfGState();
            gs.setFillOpacity(alpha);

            BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);

            PdfContentByte content;
            int total = reader.getNumberOfPages() + 1;
            for (int i = 1; i < total; i++) {
                if (isUnder) {
                    content = stamper.getUnderContent(i);
                } else {
                    content = stamper.getOverContent(i);
                }
                content.setGState(gs);
                content.beginText();
                content.setColorFill(BaseColor.BLUE);
                content.setFontAndSize(base, 50);
                content.setTextMatrix(70, 200);
                content.showTextAligned(Element.ALIGN_CENTER, mainMark, 300, 350, degree);

                content.setColorFill(BaseColor.GREEN);
                content.setFontAndSize(base, 18);
                content.showTextAligned(Element.ALIGN_CENTER, rootMark, 300, 300, 0);
                content.endText();

            }
        } finally {
            stamper.close();
            reader.close();
            is.close();
        }
    }

    /**
     *
     * @param iconPath
     *            图标
     * @param alpha
     *            透明度
     * @param degree
     *            角度
     * @param isUnder
     *            在内容下/上方加水印
     * @param is
     *            输入IO
     * @param os
     *            输出IO
     * @param rootMark
     *            页脚文本描述
     */

    private static void markImage(String iconPath, float alpha, int degree, boolean isUnder, InputStream is,
                                  OutputStream os, String rootMark) throws DocumentException, IOException {
        PdfReader reader = new PdfReader(is);
        // 关联源文件和目标文件
        PdfStamper stamper = new PdfStamper(reader, os);
        try {
            BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);

            PdfGState gs = new PdfGState();
            gs.setFillOpacity(alpha);

            PdfContentByte content;
            // 获取页数 遍历 加水印
            for (int i = 1; i <= reader.getNumberOfPages(); i++) {
                if (isUnder) {
                    content = stamper.getUnderContent(i);
                } else {
                    content = stamper.getOverContent(i);
                }

                content.setGState(gs);
                content.beginText();

                Image image = Image.getInstance(iconPath);
                image.setAlignment(Image.LEFT | Image.TEXTWRAP);
                image.setRotationDegrees(degree);
                image.setAbsolutePosition(200, 200);
                image.scaleToFit(200, 200);

                content.addImage(image);
                content.setColorFill(BaseColor.BLACK);
                content.setFontAndSize(base, 8);
                content.showTextAligned(Element.ALIGN_CENTER, rootMark, 300, 300, 0);
                content.endText();
            }
        } finally {
            stamper.close();
            reader.close();
            is.close();
        }
    }
}
